/**
 * This class implements appropriate methods to get chart of the Linear Regression 
 */
package org.wmine.visualization;

import java.awt.Color;
import java.io.IOException;
import java.io.StringBufferInputStream;
import java.util.ArrayList;

import javax.xml.parsers.ParserConfigurationException;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.wmine.core.ProjectManager;
import org.wmine.data.DataSet;
import org.wmine.data.InvalidCursorPositionException;
import org.wmine.data.TableResultSet;
import org.wmine.data.XMLDataReader;
import org.wmine.visualization.data.AbstractChartDataProvider;
import org.wmine.visualization.data.LinearRegData;
import org.wmine.visualization.data.LinearRegDataProvider;
import org.wmine.visualization.data.LinearRegData.LinearRegSingleData;
import org.wmine.visualization.eventhandlers.DisplayGraphEventHandler;

import org.xml.sax.SAXException;

/**
 * @author Rajeev Kumar Thakur
 *
 */
public class DrawLinearRegressionGraph  implements IDrawMiningAlgorithmOutput{
	
	 
	AbstractChartDataProvider reg;
	LinearRegData regressionData;
	ArrayList<LinearRegSingleData> regList;
	ArrayList<Double> xData;
	ArrayList<Double> yData;
	ArrayList<Double> xDataAttri;
	ArrayList<Double> yDataAttri;
	DataSet data;
	TableResultSet res;
	String attribOne, attribTwo, outputFileName;
	String dataFileName = "PreProcessed.xml";
	public DrawLinearRegressionGraph(String outputFileName,String attr1, String attr2) throws ParserConfigurationException, SAXException, IOException {
		this.outputFileName = outputFileName;
		attribOne = attr1;
		attribTwo = attr2; 
		xDataAttri = new ArrayList<Double>();
		yDataAttri = new ArrayList<Double>(); 
		//Xdata = new ArrayList<Double>();
		yData = new ArrayList<Double>();
		reg = new LinearRegDataProvider(outputFileName);
		regressionData = (LinearRegData) reg.getChartData();
		regList = regressionData.getLinearRegDataList();
		 data = new DataSet();
		data.setDataReader(new XMLDataReader(new StringBufferInputStream(ProjectManager.getUniqueInstance().readFile(dataFileName))));
		 res = data.getTableResultSet();
	
		//  System.out.println(attribOne);
		// System.out.println("in constructor"+attribTwo);
		// TODO Auto-generated constructor stub
	}

	public SetChartPanel drawGraph() throws ParserConfigurationException, SAXException, IOException {
		// TODO Auto-generated method stub
		
		JFreeChart chart1;
		
		
		  loadAttributeDataFromDataset();
		  
		  LinearRegSingleData singleData = findingRegressionResult();
		  calculateYaxisData(singleData);
		  
		  chart1 = setupChartProperties();
		 
		  SetChartPanel setChart = new SetChartPanel(chart1);
		//  System.out.println("inDrawLinear");
		  return setChart;
			
	}
	
	
	public void loadAttributeDataFromDataset() throws ParserConfigurationException, SAXException, IOException {
		// TODO Auto-generated method stub
	
	//	System.out.println("in Drawlingraph" );
		try {
			int cnt= 0 ;
			while(res.hasNext()){
				xDataAttri.add( new Double(res.getString(attribOne)));	
			cnt++;
			yDataAttri.add(new Double(res.getString(attribTwo)));
			}
			res.reset();
		//	System.out.println("in DrawLinear Reg : no of records :"+cnt);
	 		//System.out.println("in DrawLinear Reg :"+attribOne);
		 //	System.out.println("in DrawLinear Reg :"+attribTwo);
		  //	System.out.println(xDataAttri);
		  //	System.out.println(yDataAttri);
	 	} catch (InvalidCursorPositionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * @param attribute1
	 * @param Attribute2
	 * @return returns a regression result object for the appropriate attributes
	 */
	public LinearRegSingleData findingRegressionResult(){
		LinearRegSingleData resultOfReg = regressionData.getLinearRegSingleDataInstance();
		for (int i = 0; i < regList.size(); i++) {
			LinearRegSingleData temp = regressionData.getLinearRegSingleDataInstance();
			temp = regList.get(i);
			if (temp.getAttribute1().equals(attribOne) && temp.getAttribute2().equals(attribTwo)){
				resultOfReg = temp;
			}
		}
		return resultOfReg;
	}
	
	/**
	 * @param result
	 * calculates the Yaxis data using slope and intercept
	 */
	public void calculateYaxisData(LinearRegSingleData result) {
		Double slope, intercept;
		double y;
		slope = result.getSlope();
		intercept = result.getIntercept();
		//addXdata();
	//	System.out.println("XdataAttri  size:"+xDataAttri.size());
		for (int i = 0; i < xDataAttri.size(); i++) {
			y = xDataAttri.get(i).doubleValue()* slope.doubleValue()+ intercept.doubleValue();
			yData.add(y);
			//System.out.println("XdataAttri :"+xDataAttri.get(i)+" Ydata :"+ yData.get(i));
		}	
	}
	 
	  
	
	protected JFreeChart setupChartProperties() {
		JFreeChart chart;
		XYSeries chartSeries1 = new XYSeries("Linear Regression");
		XYSeries chartSeries2 = new XYSeries("Attribute Values");
		 
		
		//Add your values here
		for(int i = 0; i<xDataAttri.size(); i++) {
			chartSeries1.add(xDataAttri.get(i), yData.get(i));
		}
		
		for(int i = 0; i<xDataAttri.size(); i++) {
			chartSeries2.add(xDataAttri.get(i), yDataAttri.get(i));
		}

		//System.out.println("In Setup Chart properties");
		//for(int i = 0; i<XdataAttri.size(); i++) {
		//	System.out.println("attributes at ");
			//System.out.println(XdataAttri.get(i)+" "+ YdataAttri.get(i));
		//}

		XYSeriesCollection seriesCollection = new XYSeriesCollection();
		seriesCollection.addSeries(chartSeries2);
		seriesCollection.addSeries(chartSeries1);
		XYDataset dataset = seriesCollection;
		chart = ChartFactory.createXYLineChart(
				"Linear Regression",      // chart title
				 attribOne,                      // x axis label
				 attribTwo,                      // y axis label
				dataset,                  // data
				PlotOrientation.VERTICAL,
				true,                     // include legend
				true,                     // tooltips
				false                     // urls
		);

		// NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
		chart.setBackgroundPaint(Color.white);

//		final StandardLegend legend = (StandardLegend) chart.getLegend();
		//      legend.setDisplaySeriesShapes(true);

		// get a reference to the plot for further customisation...
		final XYPlot plot = chart.getXYPlot();
		plot.setBackgroundPaint(Color.white);
		//    
		plot.setDomainGridlinePaint(Color.lightGray);
		plot.setRangeGridlinePaint(Color.lightGray);

 		final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
		renderer.setSeriesLinesVisible(0, false);
		renderer.setSeriesShapesVisible(1, false);
		plot.setRenderer(renderer);
 
		// change the auto tick unit selection to integer units only...
		final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
		rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
		return chart;
	} 	
}
